/** * 通用列表组件 * 集成固定操作列、页码组件 */
<template>
  <div
    class="default-list"
    v-loading="loading"
    element-loading-background="rgba(255, 255, 255, 0.4)"
  >
    <div class="prepend-wrap">
      <slot name="prepend"></slot>
    </div>
    <!-- 列表 -->
    <el-table
      :data="tableData"
      style="border: 1px solid #ededed;"
      :max-height="style.maxLine * lineHeight || null"
      :border="true"
      :stripe="true"
    >
      <!-- 固定序号列 -->
      <el-table-column
        label="序号"
        :width="getIndexWrapWidth()"
        align="center"
        v-if="tableIndex"
        type="index"
        :index="1"
      >
      </el-table-column>

      <!-- 通过 tableItems 加载的业务字段列 -->
      <el-table-column
        v-for="item in tableItems"
        :key="item.field"
        :prop="item.field"
        :label="item.label"
        :width="item.width"
        :min-width="item.minWidth"
        :sortable="item.sortable"
        :align="item.align"
        :show-overflow-tooltip="item.showOverflowTooltip"
        v-if="checkItemShow(item)"
      >
        <template slot-scope="scope">
          <template v-if="item.type === 'button'">
            <el-button @click="item.function(scope.row)" type="text">
              <span class="text" :style="{ color: item.color }">{{
                getValueDisplay(scope.row, item)
              }}</span>
            </el-button>
          </template>
          <template v-if="item.type === 'image'">
            <custom-image
              :src="getItemImageUrl(item, scope.row)"
              :width="item.imageWidth"
              :height="item.imageHeight"
            ></custom-image>
          </template>
          <template v-if="item.type === 'SIGN_ITEM'">
            <span
              :class="getItemTextClass(item)"
              style="display:block;height:100%"
              @click="getItemTextClick(item, scope.row)"
              :style="{ color: item.color }"
              v-for="(signItem, index1) in getValueDisplay(scope.row, item)"
              :key="index1"
            >
              <a
                @click="showImage(signItem)"
                class="task_title_a"
                v-if="signItem.includes('data:image/png;base64')"
                >查看</a
              >
              <span v-else>{{ signItem }}</span>
            </span>
          </template>
          <template v-if="item.type === 'SIGN'">
            <span
              :class="getItemTextClass(item)"
              style="display:block;height:100%"
              @click="getItemTextClick(item, scope.row)"
              :style="{ color: item.color }"
              v-for="(signItem, index1) in getValueDisplay(scope.row, item)"
              :key="index1"
            >
              <span>{{ signItem["userName"] }}</span>
              <a
                @click="showImage(signItem['content'])"
                class="task_title_a"
                v-if="
                  signItem['content'] &&
                    signItem['content'].includes('data:image/png;base64')
                "
              >
                查看</a
              >
              <span v-else>{{
                signItem["content"] ? " " + signItem["content"] : ""
              }}</span>
              <span>{{ signItem["date"] ? " " + signItem["date"] : "" }}</span>
            </span>
          </template>
          <template v-if="item.type === 'TEXT'">
            <span
              :class="getItemTextClass(item)"
              @click="getItemTextClick(item, scope.row)"
              :style="{ color: item.color }"
              >{{ getValueDisplay(scope.row, item) }}</span
            >
          </template>
          <template v-if="item.type === 'DATETIME'">
            <span
              :class="getItemTextClass(item)"
              @click="getItemTextClick(item, scope.row)"
              :style="{ color: item.color }"
              >{{ getValueDisplay(scope.row, item) }}</span
            >
          </template>
          <template v-if="item.type === 'RADIO_BOX'">
            <span
              :class="getItemTextClass(item)"
              @click="getItemTextClick(item, scope.row)"
              :style="{ color: item.color }"
              >{{ getValueDisplay(scope.row, item) }}</span
            >
          </template>
          <template v-if="item.type === 'input'">
            <el-input
              v-model="scope.row[item.field]"
              :placeholder="item.placeholder"
              @change="onRowDataChange(scope.row, item)"
              :disabled="item.disabled"
            >
              <template v-if="item.unit" slot="append"
                >{{ item.unit }}
              </template>
            </el-input>
          </template>
          <template v-if="item.type === 'select'">
            <el-select
              v-model="scope.row[item.field]"
              :multiple="item.multiple"
              :collapse-tags="item.multiple"
              :placeholder="item.placeholder"
              @change="onRowDataChange(scope.row, item)"
              :disabled="item.disabled"
            >
              <el-option
                v-for="opt in item.options"
                :key="opt.code"
                :value="opt.code"
                :label="opt.name"
              ></el-option>
            </el-select>
          </template>
          <template v-if="item.type === 'checkbox'">
            <el-checkbox
              class="single"
              v-model="scope.row[item.field]"
              @change="onRowDataChange(scope.row, item)"
              :disabled="item.disabled"
              :true-label="item.trueValue"
              :false-label="item.falseValue"
            ></el-checkbox>
          </template>
        </template>
      </el-table-column>
      <!-- 固定操作按钮列 -->
      <el-table-column
        label="操作"
        :width="getBtnsWrapWidth()"
        align="center"
        v-if="tableBtns.length > 0"
      >
        <template slot-scope="scope">
          <el-button
            v-for="btn in tableBtns"
            :key="btn.label"
            @click="getBtnFunction(btn, scope.row)"
            :disabled="getBtnDisabled(btn, scope.row)"
            v-show="checkBtnShow(btn, scope.row)"
            type="text"
            >{{ btn.label }}
          </el-button>
        </template>
      </el-table-column>
    </el-table>
    <!-- 页码组件 -->
    <el-pagination
      @size-change="changePageSize"
      @current-change="changePage"
      :current-page="page.index"
      :page-sizes="page.sizes"
      :page-size="page.size"
      :layout="page.layout"
      :total="page.total"
      background
    >
    </el-pagination>
  </div>
</template>
<script>
export default {
  data() {
    return {
      // 列表行高
      lineHeight: 45,
      // 表单样式
      style: {},
      // 页码组件数据对象
      page: {
        index: 1,
        sizes: [10, 20, 50, 100],
        size: 10,
        layout: "total, sizes, prev, pager, next, jumper",
        total: 0
      },
      dialogVisible: false,
      dialogImageUrl: ""
    };
  },
  mounted() {
    console.log(this.tableItems, "tableItems");
  },
  props: {
    loading: { type: Boolean, default: false },
    tableIndex: { type: Boolean, default: false },
    tableData: {
      type: Array,
      default: function() {
        return [];
      }
    },
    tableItems: {
      type: Array,
      default: function() {
        return [];
      }
    },
    tableStyle: {
      type: Object,
      default: function() {
        return {};
      }
    },
    tableBtns: {
      type: Array,
      default: function() {
        return [];
      }
    },
    tablePage: {
      type: Object,
      default: function() {
        return {};
      }
    }
  },
  watch: {
    tableItems: function(list) {
      this.setTablePageData();
      this.setTableItemsData();
      this.setTableRulesData();
    },
    tableStyle: function(v) {
      this.setTableStyleDefault();
    },
    "tablePage.total": function(total) {
      this.page.total = total;
    }
  },
  methods: {
    showImage(url) {
      this.$emit("show-sign-image", url);
    },
    getIndexWrapWidth: function() {
      if (this.tableIndex) {
        return 30 + 22;
      }
      return 0;
    },
    getBtnsWrapWidth: function() {
      if (this.tableBtns.length) {
        return (
          30 +
          this.tableBtns.length * 22 +
          this.tableBtns
            .map(v => v.label.length)
            .reduce((prev, curr) => {
              return prev + curr;
            }) *
            15
        );
      }
      return 0;
    },
    getBtnDisabled: function(btn, row) {
      if (typeof btn.disabled === "function") {
        return btn.disabled(row);
      }
      if (typeof btn.disabled === "boolean") {
        return btn.disabled;
      }
      return false;
    },
    getBtnFunction: function(btn, row) {
      if (btn.function) {
        btn.function(row);
      }
    },
    // 判断按钮是否显示
    checkBtnShow: function(btn, row) {
      if (typeof btn.isShow === "function") {
        return btn.isShow(row);
      }
      if (typeof btn.isShow === "boolean") {
        return btn.isShow;
      }
      return true;
    },
    getItemTextClass: function(item) {
      let className = ["text"];
      if (item.onClick) {
        className.push("click-able");
      }
      return className;
    },
    getItemTextClick: function(item, row) {
      if (item.onClick) {
        item.onClick(row);
      }
    },
    // 获取图片组件路径
    getItemImageUrl: function(item, row) {
      if (item.imageUrl && typeof item.imageUrl === "function") {
        return item.imageUrl(row);
      }
      return row[item.field];
    },
    // 获取二维码数据
    getItemQrcode: function(item, row) {
      if (item.qrcode && typeof item.qrcode === "function") {
        return item.qrcode(row);
      }
      return row[item.field];
    },
    // 处理文字展示逻辑
    getValueDisplay: function(row, item) {
      let value = row[item.field];
      if (typeof item.template === "function") {
        return item.template(value, row, item);
      }
      if (item.dictionary) {
        return this.showDictionary(item.dictionary, value);
      }
      return value;
    },
    // 判断字段列是否显示
    checkItemShow: function(item) {
      if (typeof item.isShow === "function") {
        return item.isShow();
      }
      if (typeof item.isShow === "boolean") {
        return item.isShow;
      }
      return true;
    },
    // 当明细行数据发生改变时做的处理
    onRowDataChange: function(row, item) {
      if (item.onChange && typeof item.onChange === "function") {
        item.onChange(row, item);
      }
    },
    setTablePageData: function() {
      const { pageSize, pageSizes, pageNum, total } = this.tablePage;
      this.page.size = pageSize || 10;
      this.page.sizes = pageSizes || [10, 20, 50, 100];
      this.page.index = pageNum || 1;
      this.page.total = total || 0;
    },
    setTableItemsData: function() {
      this.tableItems.forEach(item => {
        if (!item.opt_pre) {
          item.opt_pre = "请选择";
        }
        if (!item.type) {
          item.type = "text";
        }
        if (!item.align) {
          item.align = "center";
        }
        if (item.type === "input") {
          item.opt_pre = "请输入";
        }
        if (!item.placeholder) {
          item.placeholder = item.opt_pre + item.label;
        }
        if (typeof item.disabled === "undefined") {
          item.disabled = true;
        }
        if (typeof item.showOverflowTooltip === "undefined") {
          if (item.type === "text") {
            item.showOverflowTooltip = true;
          } else {
            item.showOverflowTooltip = false;
          }
        }
        if (item.type === "checkbox") {
          if (item.useDictionary === true) {
            item.trueValue = this.Dictionary.IS_TRUE;
            item.falseValue = this.Dictionary.IS_FALSE;
          }
          if (typeof item.falseValue !== typeof item.trueValue) {
            console.error(
              `[${item.label}:${item.field}] 的 falseValue 和 trueValue 必须同时定义`
            );
          }
        }
      });
    },
    setTableRulesData: function() {},
    setTableStyleDefault: function() {
      let { maxLine } = this.tableStyle;
      maxLine = maxLine ? parseInt(maxLine) + 1 : 0;

      this.style = { maxLine };
    },
    changePage: function(page) {
      this.page.index = page;
      this.doPageChange();
    },
    changePageSize: function(size) {
      this.page.index = 1;
      this.page.size = size;
      this.doPageChange();
    },
    doPageChange: function() {
      this.tablePage.pageNum = this.page.index;
      this.tablePage.pageSize = this.page.size;
      this.$emit("search-action");
    }
  },
  created() {
    this.setTablePageData();
    this.setTableItemsData();
    this.setTableRulesData();
    this.setTableStyleDefault();
  }
};
</script>
<style lang="scss" scoped>
.prepend-wrap {
  // padding: 12px 0;
}

.el-table /deep/ {
  width: 100%;

  .cell {
    /*height: 28px;*/
    line-height: 22px;
  }
}

.el-table:before {
  height: 0;
}

.el-pagination /deep/ {
  margin-top: 20px;
  text-align: right;

  span {
    font-size: 13px;
  }

  .el-pagination__total {
    float: left;
    margin-right: 24px;
  }

  .el-pagination__sizes {
    float: left;

    .el-input {
      width: 90px;
    }

    .el-input__inner {
      padding: 0 20px 0 6px;
      font-size: 12px;
    }

    .el-input__suffix {
      .el-input__validateIcon {
        display: none;
      }
    }
  }

  .el-pagination__jump {
    .el-input {
      margin: 0 10px;
    }
  }

  .btn-prev,
  .btn-next,
  .el-pager li {
    margin: 0 3px;
    min-width: 28px;
    height: 28px;
    line-height: 28px;
    border-radius: 5px;
  }
}
</style>
